package scalab.core.interpreter

/**
* This is scalab's emulated interpreter. It is made of 
*	a preprocessor followed by a scala compiler and 
*	a scala runner.
*/
object Interpreter{

	import scalab.core.component._
	import scalab.filters.selectors.Files
	import scala.collection.immutable.HashSet

	//debug
	lazy val name = "Interpreter"

	import scalab.caches.NoCache
	import scalab.caches.ccp.{SimpleConservativeCCP, AccurateConservativeCCP}
	import scalab.caches.cdp._
	import scalab.caches.cep.LRUCEP
	import scalab.tasks.compilers.Scalac
	import scalab.tasks.runners.Scala

	def interpret: Boolean = {
    
		//-----Building Boot Caches
		val noCache = NoCache()
		val cacheDir = Settings.bootCacheDir
		//should be AccurateConservative to be more efficient...
		val conservativeCache = new SimpleConservativeCCP with DigestCDP with LRUCEP{
			val name = "SCCCP"
		}
		if(Settings.bootThresholdSize > conservativeCache.getEvictedSize){
			conservativeCache.setThresholdSize(Settings.bootThresholdSize)
			conservativeCache.setEvictedSize(Settings.bootEvictedSize)
		}
		else{
			conservativeCache.setEvictedSize(Settings.bootEvictedSize)
			conservativeCache.setThresholdSize(Settings.bootThresholdSize)
		}
		
		
		val caches = List(noCache, conservativeCache)
		caches foreach {c => c.setCacheDir(cacheDir + c.name + "/")}

		//preprocessor
		val preprocessor = Preprocessor()
		preprocessor.identifier = preprocessor.name //boot components' ids are hard coded.
		preprocessor setCache noCache //AccurateConservative cache, later

		//compiler
		val compiler = Scalac("Compiler")
		compiler setCache conservativeCache 
		compiler.identifier = compiler.name

		//runner
		val runner = Scala("Runner", List("BuildGraph", Settings.targetName.toString))
		runner setCache noCache
		runner.identifier = runner.name

		//todo get SCALAB_HOME...
		//boot graph
		Universe -> Files("classes/") >> (compiler.classpath, runner.classpath)
		Universe -> Files("lib/hsqldb.jar") -> runner.classpath
		Universe -> Files(Settings.mainBuildFile) -> preprocessor -> compiler.srcs
		compiler.productDirectories -> runner.classpath

		//target
		val target = Target("build_products/", runner)
		target setMessageLevel scalab.utils.Reporter.NOTHING_LEVEL //disable messages

		//reset instance counter
		Component.instanceNumber = 0
	
		//reset components sets
		val empty = HashSet.empty[Component] + Universe
		Component.allComps = empty
		SinkComponent.allSinkComps = empty.asInstanceOf[Set[SinkComponent]]
		BlackBox.allBoxes = empty.asInstanceOf[Set[BlackBox]]
		ExecutableComponent.allExecComps = empty.asInstanceOf[Set[ExecutableComponent]]
		Filter.allFilters = empty.asInstanceOf[Set[Filter]]
		Task.allTasks = empty.asInstanceOf[Set[Task]]
		Target.allTargets = empty.asInstanceOf[Set[Target]]

		//run build
		target.update
  }
}
